package com.zhouyu;

import com.zhouyu.thirteen.UserServiceInterface;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//import org.springframework.cglib.proxy.*;


/**
 * https://www.yuque.com/books/share/5f19528d-d89b-4b69-a7bd-9f436a2dd734/bngtc3#UEtOR
 */
public class Test13 {


	public static void main(String[] args) {


		/**
		 * cglib动态代理 使用
		 */
		/*
		UserService target = new UserService();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(UserService.class);
		enhancer.setCallbacks(new Callback[]{(MethodInterceptor) (o, method, objects, methodProxy) -> {
			System.out.println("before...");
			method.invoke(target,objects);
			System.out.println("after...");
			return null;
		},NoOp.INSTANCE});

		enhancer.setCallbackFilter(new CallbackFilter() {
			@Override
			public int accept(Method method) {
				if (method.getName().equals("test")) {
					return 0;
				}
				return 1;

			}
		});


		UserService userService = (UserService) enhancer.create();
		userService.a();
		userService.test();*/

		/**
		 * jdk 动态代理
		 */
		/*UserServiceInterface target = new UserService();
		UserServiceInterface userServiceInterface = (UserServiceInterface)Proxy.newProxyInstance(UserServiceInterface.class.getClassLoader(), new Class[]{UserServiceInterface.class}, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				if (method.getName().equals("test")) {
					System.out.println("before...");
				}

				Object o = method.invoke(target);

				if (method.getName().equals("test")) {
					System.out.println("after...");
				}

				return o;
			}
		});

		userServiceInterface.a();
		userServiceInterface.test();*/

		/**
		 * ProxyFactory 类似上面两种动态代理的使用方式
		 */
		/*UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
		//加了这一句就是使用jdk 动态代理
//		proxyFactory.setInterfaces(UserServiceInterface.class);
		proxyFactory.addAdvice(new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				System.out.println("before...");
				Object result = invocation.proceed();
				System.out.println("after...");
				return result;
			}
		});

		UserServiceInterface userService = (UserServiceInterface) proxyFactory.getProxy();
		userService.test();*/

		/**
		 * 测试几个 advice
		 */
		/*UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
		proxyFactory.addAdvice(new ZhouyuBeforeAdvise());
		proxyFactory.addAdvice(new ZhouyuAfterReturningAdvise());
		proxyFactory.addAdvice(new ZhouyuThrowsAdvice());
		proxyFactory.addAdvice(new ZhouyuAroundAdvise());

		UserServiceInterface userService = (UserServiceInterface) proxyFactory.getProxy();
		userService.test();*/

		/**
		 * Advisor 使用该功能可以区分只对那些方法进行增强
		 */

		/*UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
		proxyFactory.addAdvisor(new PointcutAdvisor() {
			@Override
			public Pointcut getPointcut() {
				return new StaticMethodMatcherPointcut() {
					@Override
					public boolean matches(Method method, Class<?> targetClass) {
						return method.getName().equals("test");
					}
				};
			}

			@Override
			public Advice getAdvice() {
				return new MethodInterceptor() {
					@Override
					public Object invoke(MethodInvocation invocation) throws Throwable {
						System.out.println("before...");
						Object result = invocation.proceed();
						System.out.println("after...");
						return result;
					}
				};
			}

			@Override
			public boolean isPerInstance() {
				return false;
			}
		});

		UserServiceInterface userService = (UserServiceInterface) proxyFactory.getProxy();
		userService.test();*/

		/**
		 * ProxyFactoryBean BeanNameAutoProxyCreator->局限 DefaultAdvisorAutoProxyCreator->最强大
		 *
		 * DefaultAdvisorAutoProxyCreator 的功能
		 * 通过DefaultAdvisorAutoProxyCreator会直接去找所有Advisor类型的Bean，
		 * 根据Advisor中的PointCut和Advice信息，确定要代理的Bean以及代理逻辑。
		 */
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig13.class);
		UserServiceInterface userServiceProxy = (UserServiceInterface) context.getBean("userService");
		userServiceProxy.test();


		/**
		 * aspectj 跟spring实现对应关系
		 * Advice在Spring AOP中对应API
		 * 上面说到的Aspject中的注解，其中有五个是用来定义Advice的，表示代理逻辑，以及执行时机：
		 * 1. @Before
		 * 2. @AfterReturning
		 * 3. @AfterThrowing
		 * 4. @After
		 * 5. @Around
		 *
		 * 我们前面也提到过，Spring自己也提供了类似的执行实际的实现类：
		 * 1. 接口MethodBeforeAdvice，继承了接口BeforeAdvice
		 * 2. 接口AfterReturningAdvice
		 * 3. 接口ThrowsAdvice
		 * 4. 接口AfterAdvice
		 * 5. 接口MethodInterceptor
		 */

	}
}
